/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://gitee.com/shenyczz/csharp_csk
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/
using System;
using System.Diagnostics;

namespace CSharpKit.Convertions
{
    public sealed class ArrayConverter
    {
        ArrayConverter() { }
        public static readonly ArrayConverter Instance = new ArrayConverter();


        #region Array1D

        /// <summary>
        /// 一维数组转换数据类型
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="outs"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <returns></returns>
        public void Array1D<TSource, TOut>(in TSource[] sources, out TOut[] outs)
        {
            outs = default;

            try
            {
                int len = sources.Length;

                var vtype = typeof(TOut);
                var vdest = new TOut[len];

                for (int i = 0; i < len; i++)
                {
                    vdest[i] = (TOut)Convert.ChangeType(sources[i], vtype);
                }

                outs = vdest;
            }
            catch (Exception ex)
            {
                var err = ex.Message;
#if DEBUG
                Debug.WriteLine(ex);
#endif
            }

            return;
        }

        #endregion

        #region Array1D2D

        public T[,] Array1D2D<T>(T[] tSource, int rows, int cols)
        {
            Array1D2D(tSource, rows, cols, out T[,] tOut);
            return tOut;
        }
        public void Array1D2D<T>(T[] tSource, int rows, int cols, out T[,] tOut)
        {
            tOut = null;

            try
            {
                var vtemp = tOut;
                {
                    vtemp = new T[rows, cols];
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < cols; j++)
                        {
                            vtemp[i, j] = tSource[i * cols + j];
                        }
                    }
                }
                tOut = vtemp;
            }
            catch (Exception ex)
            {
                var err = ex.Message;
#if DEBUG
                Debug.WriteLine(ex);
#endif
                throw;
            }

            return;
        }

        #endregion

        #region Array2D

        /// <summary>
        /// 二维数组转换数据类型
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="outs"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <returns></returns>
        public void Array2D<TSource, TOut>(TSource[,] sources, out TOut[,] outs)
        {
            Array2D(sources,
                (TOut)Convert.ChangeType(1, typeof(TOut)),
                (TOut)Convert.ChangeType(0, typeof(TOut)),
                null,
                out outs);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uSource"></param>
        /// <param name="scale"></param>
        /// <param name="offset"></param>
        /// <param name="isValid"></param>
        /// <param name="vOut"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <returns></returns>
        public void Array2D<TSource, TOut>(TSource[,] uSource, TOut scale, TOut offset, Predicate<double> isValid, out TOut[,] vOut)
        {
           vOut = default;

            try
            {
                int rows = uSource.GetLength(0);
                int cols = uSource.GetLength(1);

                dynamic sc = scale;
                dynamic of = offset;

                //var vtype = typeof(V);
                TOut[,] vdest = new TOut[rows, cols];

                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        dynamic sv = uSource[i, j];

                        if (isValid != null)
                        {
                            vdest[i, j] = isValid(sv) ? sv * sc + of : sv;
                        }
                        else
                        {
                            vdest[i, j] = sv * sc + of;
                        }
                    }
                }

                vOut = vdest;
            }
            catch (Exception ex)
            {
                var err = ex.Message;
#if DEBUG
                Debug.WriteLine(ex);
#endif
                throw;
            }

            return;
        }

        #endregion

        #region Array2D1D

        /// <summary>
        /// 二维数组转换为一维数组
        /// </summary>
        /// <param name="datas"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] Array2D1D<T>(T[,] datas)
        {
            Array2D1D(datas, out T[] raws, out int rows, out int cols);
            return raws;
        }

        public void Array2D1D<T>(T[,] datas, out T[] raws, out int rows, out int cols)
        {
            rows = 0;
            cols = 0;
            raws = null;

            try
            {
                rows = datas.GetLength(0);
                cols = datas.GetLength(1);

                var vtemp = new T[cols * rows];
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        vtemp[i * cols + j] = datas[i, j];
                    }
                }

                raws = vtemp;
            }
            catch (Exception ex)
            {
                var err = ex.Message;
#if DEBUG
                Debug.WriteLine(ex);
#endif
                throw;
            }

            return;
        }

        #endregion

        #region ArrayMirrory2D

        /// <summary>
        /// 二维数组南北镜像
        /// </summary>
        /// <param name="tSource"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[,] ArrayMirrory2D<T>(T[,] tSource)
        {
            ArrayMirrory2D(tSource, out T[,] tOut);
            return tOut;
        }
        public void ArrayMirrory2D<T>(T[,] tSource, out T[,] tOut)
        {
            tOut = default;

            try
            {
                var vtemp = tOut;
                {
                    int rows = tSource.GetLength(0);
                    int cols = tSource.GetLength(1);

                    vtemp = new T[rows, cols];
                    for (int i = 0; i < rows; i++)
                    {
                        int ii = (rows - 1) - i;
                        for (int j = 0; j < cols; j++)
                        {
                            vtemp[ii, j] = tSource[i, j];
                        }
                    }
                }
                tOut = vtemp;
            }
            catch (Exception ex)
            {
                var err = ex.Message;
#if DEBUG
                Debug.WriteLine(ex);
#endif
                throw;
            }

            return;
        }

        #endregion




        //}}@@@
    }





}
